module func_factory; 
use test_mod;
use vec_mod;
implicit none; 
logical, save :: FUNC_FACTORY_TRACE_ENTRY = .FALSE.;
contains 


function new_func_exp(px) result(py);   implicit none;  
  real(R14), dimension(:), pointer :: px, py;      
  call dbg_info("-->new_func_exp()");
  py => new_vec_from(px);  call dbg_vec("py=", py);
  py = EXP(px);
  return;
end function

function new_func_sin(px) result(py);   implicit none;  
  real(R14), dimension(:), pointer :: px, py;      
  call dbg_info("-->new_func_sin()");
  py => new_vec_from(px);  call dbg_vec("py=", py);
  py = SIN(px);
  return;
end function

function new_func_cos(px) result(py);   implicit none;  
  real(R14), dimension(:), pointer :: px, py;      
  call dbg_info("-->new_func_cos()");
  py => new_vec_from(px);  call dbg_vec("py=", py);
  py = COS(px);
  return;
end function

function new_func_polynom(px, coeff) result(py);   implicit none;  
  real(R14), dimension(:), intent(IN) :: coeff;      
  real(R14), dimension(:), pointer :: px, py;      
  integer :: i;
  call dbg_info("-->new_func_polynom()");
  py => new_vec_from(px);  call dbg_vec("py=", py);
  do i = LBOUND(px, 1), UBOUND(px, 1)
    py(i) = func_polynom(px(i), coeff);
  end do
  return;
end function


real(R14) function func_polynom(x, coeff) result(y);   implicit none;  
  real(R14), dimension(:), intent(IN) :: coeff;      
  real(R14), intent(IN) :: x;      
  real(R14) :: powx;      
  integer :: i, min_i;
  call dbg_info("-->func_polynom()", FUNC_FACTORY_TRACE_ENTRY);
  call assert_true("SIZE(coeff, 1) > 0", SIZE(coeff, 1) > 0);
  min_i = LBOUND(coeff, 1); 
  powx = 1.;
  y = coeff(min_i);
  do i = min_i + 1, UBOUND(coeff, 1)
    powx = powx * x;
    y = y + powx * coeff(i);
  end do
  return;
end function

end module 